home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-1.iso / Files / Util / I / IdleTime Init 1.0.sit / IdleTime INIT 1.0 / Sample C Code / idlewatcher.c next >
Encoding:
C/C++ Source or Header  |  1993-07-25  |  8.3 KB  |  468 lines  |  [TEXT/KAHL]

  1.  
  2. /*
  3. © Copyright 1993 UserLand Software, Inc.  All Rights Reserved.
  4.  
  5. To see how this sample program uses the IdleTime INIT, jump to 
  6. the end and look at the idleMessage routine. There's a detailed
  7. comment at the top of that routine.
  8.  
  9. If you have any questions, comments or suggestions, please get 
  10. in touch through one of UserLand’s on-line services. If you’re 
  11. an AppleLink user, check out the UserLand Discussion Board under 
  12. the Third Parties icon. On CompuServe, visit the UserLand Forum 
  13. in the Computing Support section, or enter GO USERLAND at any 
  14. ! prompt. On America On-Line, enter the keyword USERLAND.
  15.  
  16. Hope you like it!
  17.  
  18. UserLand Software
  19. July 25, 1993
  20. */
  21.  
  22.  
  23. #include <AppleEvents.h>
  24. #include <GestaltEqu.h>
  25.  
  26.  
  27. #define applemenu 128 
  28. #define aboutitem 1 
  29.  
  30. #define filemenu 129
  31. #define quititem 1
  32.  
  33. MenuHandle happlemenu, hfilemenu; 
  34.  
  35. WindowPtr mainwindow = nil;
  36.  
  37. Str255 windowmessage; 
  38.  
  39. Boolean flexitmainloop = false; 
  40.  
  41. Boolean flcurrentlyactive = true;
  42.  
  43.  
  44.  
  45.  
  46. static void initMacintosh (void) {
  47.  
  48.     /*
  49.     the magic stuff that every Macintosh application needs to do 
  50.     before doing anything else.
  51.     */
  52.  
  53.     short i;
  54.         
  55.     MaxApplZone ();
  56.     
  57.     for (i = 0; i < 10; i++) 
  58.         MoreMasters ();
  59.     
  60.     InitGraf (&qd.thePort);
  61.     
  62.     InitFonts ();
  63.     
  64.     FlushEvents (everyEvent, 0);
  65.     
  66.     InitWindows ();
  67.     
  68.     InitMenus ();
  69.     
  70.     TEInit ();
  71.     
  72.     InitDialogs (nil);
  73.     
  74.     InitCursor ();
  75.     
  76.     for (i = 0; i < 5; i++) { /*register with Multifinder*/
  77.         
  78.         EventRecord ev;
  79.         
  80.         EventAvail (everyEvent, &ev); /*see TN180 -- splash screen*/
  81.         } /*for*/
  82.     } /*initMacintosh*/
  83.  
  84.  
  85. static void initAppMenus (void) {
  86.     
  87.     happlemenu = GetMenu (applemenu); 
  88.     
  89.     AddResMenu (happlemenu, 'DRVR'); 
  90.     
  91.     InsertMenu (happlemenu, 0); 
  92.     
  93.     hfilemenu = GetMenu (filemenu); 
  94.     
  95.     InsertMenu (hfilemenu, 0);
  96.     
  97.     DrawMenuBar ();
  98.     } /*initAppMenus*/
  99.  
  100.  
  101. static Boolean initMainWindow (void) {
  102.     
  103.     mainwindow = GetNewWindow (128, nil, (WindowPtr) -1);
  104.     
  105.     if (mainwindow == nil)
  106.         return (false);
  107.     
  108.     ShowWindow (mainwindow);
  109.     
  110.     return (true);
  111.     } /*initMainWindow*/
  112.  
  113.  
  114. static void ellipsize (Str255 s, short width) {
  115.  
  116.     /*
  117.     if the string fits inside the given number of pixels, fine -- do nothing
  118.     and return.
  119.     
  120.     if not, return a string that does fit, with ellipses representing the 
  121.     deleted characters.  ellipses are generated by pressing option-semicolon.
  122.     */
  123.     
  124.     char len;
  125.     short newwidth;
  126.     
  127.     if ((newwidth = StringWidth (s)) <= width) /*nothing to do, the string fits*/
  128.         return;
  129.     
  130.     len = s [0]; /* current length in characters*/
  131.     
  132.     width -= CharWidth ('…'); /* subtract width of ellipses*/
  133.         
  134.     do { /*until it fits (or we run out of characters)*/
  135.     
  136.         newwidth -= CharWidth (s [len]);
  137.         
  138.         --len;
  139.     } while ((newwidth > width) && (len != 0));
  140.     
  141.     ++len; /*make room for the ellipses*/
  142.     
  143.     s [len] = '…'; 
  144.     
  145.     s [0] = (char) len;
  146.     } /*ellipsize*/
  147.  
  148.  
  149. static void centerString (Rect r, Str255 s) {
  150.     
  151.     /*
  152.     draw the string in the current font, size and style, centered inside
  153.     the indicated rectangle.
  154.     */
  155.     
  156.     short rh = r.bottom - r.top;
  157.     short rw = r.right - r.left;
  158.     short h, v;
  159.     FontInfo fi;
  160.     
  161.     GetFontInfo (&fi);
  162.     
  163.     ellipsize (s, rw); /*make sure it fits inside the rectangle, width-wise*/
  164.     
  165.     h = r.left + ((rw - StringWidth (s)) / 2);
  166.     
  167.     v = r.top + ((rh - (fi.ascent + fi.descent)) / 2) + fi.ascent;
  168.     
  169.     MoveTo (h, v);
  170.     
  171.     ClipRect (&r);
  172.     
  173.     DrawString (s);
  174.     } /*centerString*/
  175.  
  176.  
  177. static void setFontSizeStyle (short fontnum, short fontsize, short fontstyle) {
  178.  
  179.     TextFont (fontnum);
  180.     
  181.     TextSize (fontsize);
  182.     
  183.     TextFace (fontstyle);
  184.     } /*setFontSizeStyle*/
  185.     
  186.     
  187. static void updateMainWindow (void) {
  188.     
  189.     Rect r;
  190.     Str255 s;
  191.     
  192.     r = (*mainwindow).portRect;
  193.     
  194.     EraseRect (&r);
  195.     
  196.     setFontSizeStyle (helvetica, 18, bold);
  197.     
  198.     centerString (r, windowmessage);
  199.     
  200.     NumToString (FreeMem () / 1024, s);
  201.     
  202.     MoveTo (r.left + 3, r.bottom - 3);
  203.     
  204.     setFontSizeStyle (geneva, 9, 0);
  205.     
  206.     DrawString (s);
  207.     
  208.     DrawString ("\pK");
  209.     } /*updateMainWindow*/
  210.     
  211.     
  212. static void handleUpdate (EventRecord *ev) {
  213.     
  214.     WindowPtr w;
  215.     
  216.     w = (WindowPtr) (*ev).message;
  217.     
  218.     BeginUpdate (w);
  219.     
  220.     SetPort (w);
  221.     
  222.     updateMainWindow ();
  223.     
  224.     EndUpdate (w);
  225.     } /*handleUpdate*/
  226.  
  227.  
  228. static void handleDrag (EventRecord *ev, WindowPtr w) {
  229.     
  230.     Rect r;
  231.  
  232.     r = qd.screenBits.bounds; 
  233.     
  234.     r.top = r.top + GetMBarHeight (); 
  235.     
  236.     InsetRect (&r, 4, 4);
  237.     
  238.     DragWindow (w, (*ev).where, &r);
  239.     } /*handleDrag*/
  240.  
  241.  
  242. static void handleMenu (long codeword) {
  243.     
  244.     short idmenu, iditem;
  245.     
  246.     iditem = LoWord (codeword);
  247.     
  248.     idmenu = HiWord (codeword);
  249.     
  250.     switch (idmenu) {
  251.     
  252.         case applemenu: 
  253.             switch (iditem) {
  254.                 
  255.                 case aboutitem:
  256.                     Alert (262, nil);
  257.                     
  258.                     break;
  259.             
  260.                 default: {
  261.                     Str255 s;
  262.                     
  263.                     GetItem (happlemenu, iditem, s);
  264.                     
  265.                     OpenDeskAcc (s);
  266.                     
  267.                     break;
  268.                     }
  269.                 } /*switch*/
  270.             
  271.             break; /*apple menu*/
  272.  
  273.         case filemenu: 
  274.             switch (iditem) {
  275.                 
  276.                 case quititem:
  277.                     flexitmainloop = true;
  278.                     
  279.                     break;
  280.                 } /*switch*/
  281.             
  282.             break; /*file menu*/
  283.             
  284.         } /*switch*/
  285.         
  286.     exit:
  287.     
  288.     HiliteMenu (0);
  289.     } /*handleMenu*/
  290.  
  291.  
  292. static void handleMouse (EventRecord *ev) {
  293.  
  294.     short part;
  295.     WindowPtr w;
  296.     
  297.     switch (FindWindow ((*ev).where, &w)) {
  298.     
  299.         case inMenuBar: 
  300.             handleMenu (MenuSelect ((*ev).where)); 
  301.             
  302.             break;
  303.         
  304.         case inSysWindow:
  305.             SystemClick (ev, w); 
  306.             
  307.             break;
  308.         
  309.         case inDrag:
  310.             handleDrag (ev, w);
  311.             
  312.             break;
  313.         } /*switch*/
  314.     } /*handleMouse*/
  315.  
  316.  
  317. static void handleEvent (EventRecord *ev) { 
  318.     
  319.     switch ((*ev).what) {
  320.     
  321.         case keyDown: case autoKey: 
  322.             if ((*ev).modifiers & cmdKey)
  323.                 handleMenu (MenuKey ((*ev).message & charCodeMask)); 
  324.             
  325.             break;
  326.             
  327.         case mouseDown:
  328.             handleMouse (ev);
  329.             
  330.             break;
  331.         
  332.         case updateEvt:
  333.             handleUpdate (ev);
  334.             
  335.             break;
  336.         
  337.         case osEvt:
  338.             flcurrentlyactive = ((*ev).message & resumeFlag) != 0;
  339.             
  340.             break;
  341.         
  342.         case kHighLevelEvent:
  343.             AEProcessAppleEvent (ev);
  344.             
  345.             break;
  346.         } /*switch*/
  347.     } /*handleEvent*/
  348.  
  349.  
  350. static void AEReturnError (AppleEvent *reply, OSErr errornum, Str255 errorstring) {
  351.     
  352.     AEPutParamPtr (reply, keyErrorNumber, typeShortInteger, (Ptr) &errornum, sizeof (errornum));
  353.         
  354.     AEPutParamPtr (reply, keyErrorString, typeChar, (Ptr) &errorstring [1], errorstring [0]);
  355.     } /*AEReturnError*/
  356.     
  357.         
  358. static pascal OSErr openAppEvent (AppleEvent *event, AppleEvent *reply, long refcon) {
  359.     
  360.     return (noErr);
  361.     } /*openAppEvent*/
  362.  
  363.  
  364. static pascal OSErr openDocEvent (AppleEvent *event, AppleEvent *reply, long refcon) {
  365.     
  366.     return (noErr);
  367.     } /*openDocEvent*/
  368.     
  369.         
  370. static pascal OSErr printEvent (AppleEvent *event, AppleEvent *reply, long refcon) {
  371.     
  372.     return (noErr);
  373.     } /*printEvent*/
  374.     
  375.     
  376. static pascal OSErr quitEvent (AppleEvent *event, AppleEvent *reply, long refcon) {
  377.     
  378.     flexitmainloop = true;
  379.     
  380.     return (noErr);
  381.     } /*quitEvent*/
  382.     
  383.     
  384. static Boolean installhandlers (void) {
  385.  
  386.     if (AEInstallEventHandler (kCoreEventClass, kAEOpenApplication, openAppEvent, 0, false) != noErr)
  387.         return (false);
  388.     
  389.     if (AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments, openDocEvent, 0, false) != noErr)
  390.         return (false);
  391.     
  392.     if (AEInstallEventHandler (kCoreEventClass, kAEPrintDocuments, printEvent, 0, false) != noErr)
  393.         return (false);
  394.     
  395.     if (AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, quitEvent, 0, false) != noErr)
  396.         return (false);
  397.     
  398.     return (true);
  399.     } /*installhandlers*/
  400.     
  401.     
  402. static void idleMessage (void) {
  403.     
  404.     /*
  405.     this is the central routine in this sample program. first we call the INIT using
  406.     Gestalt, to determine how many ticks it's been since the user did something.
  407.     
  408.     we divide this number by 60 to get the number of seconds. then we compare it
  409.     against the last value we displayed. if it hasn't changed, we return.
  410.     
  411.     otherwise, we create the string, smash the current port (commercial programs
  412.     couldn't get away with this, but this is sample code...) and remember the value
  413.     we displayed for the next time thru the loop.
  414.     */
  415.     
  416.     static long lastsecs = 0;
  417.     long ticks, secs;
  418.     Str255 s;
  419.     
  420.     if (Gestalt ('idle', &ticks) != noErr) /*IdleTime INIT is not installed*/
  421.         return;
  422.         
  423.     secs = ticks / 60;
  424.         
  425.     if (secs == lastsecs) /*only re-display if it changed*/
  426.         return;
  427.             
  428.     NumToString (secs, windowmessage);
  429.  
  430.     SetPort (mainwindow);
  431.     
  432.     InvalRect (&(*mainwindow).portRect);
  433.         
  434.     lastsecs = secs; /*remember for next time*/
  435.     } /*idleMessage*/
  436.     
  437.  
  438. void main (void) {
  439.     
  440.     EventRecord ev;
  441.     
  442.     initMacintosh ();
  443.     
  444.     if (!installhandlers ()) {
  445.     
  446.         Alert (261, nil); /*couldn't install Apple Event handlers*/
  447.         
  448.         return;
  449.         }
  450.     
  451.     initAppMenus ();
  452.     
  453.     initMainWindow ();
  454.     
  455.     while (!flexitmainloop) {
  456.         
  457.         WaitNextEvent (everyEvent, &ev, 1, nil);
  458.         
  459.         handleEvent (&ev);
  460.         
  461.         idleMessage ();
  462.         } /*while*/
  463.     } /*main*/
  464.  
  465.  
  466.  
  467.  
  468.